/**
 * 请求验证中间件
 */

/**
 * 验证URL格式
 * @param {string} url - 要验证的URL
 * @returns {boolean}
 */
function isValidUrl(url) {
  try {
    new URL(url);
    return true;
  } catch {
    return false;
  }
}

/**
 * 验证文件名
 * @param {string} fileName - 要验证的文件名
 * @returns {boolean}
 */
function isValidFileName(fileName) {
  if (!fileName || typeof fileName !== 'string') {
    return false;
  }

  // 检查长度
  if (fileName.length > 200) {
    return false;
  }

  // 检查不允许的字符
  const invalidChars = /[<>:"/\\|?*\x00-\x1f]/;
  if (invalidChars.test(fileName)) {
    return false;
  }

  // 不能以点开头
  if (fileName.startsWith('.')) {
    return false;
  }

  return true;
}

/**
 * 验证任务ID格式（UUID v4）
 * @param {string} taskId - 任务ID
 * @returns {boolean}
 */
function isValidTaskId(taskId) {
  if (!taskId || typeof taskId !== 'string') {
    return false;
  }

  const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
  return uuidRegex.test(taskId);
}

/**
 * 验证添加下载任务的请求
 */
function validateAddDownload(req, res, next) {
  const { url, customFileName } = req.body;

  // 验证URL
  if (!url || typeof url !== 'string') {
    return res.status(400).json({
      success: false,
      error: 'URL参数是必需的且必须是字符串'
    });
  }

  if (!isValidUrl(url)) {
    return res.status(400).json({
      success: false,
      error: 'URL格式无效'
    });
  }

  // 验证自定义文件名（可选）
  if (customFileName !== undefined && customFileName !== null) {
    if (typeof customFileName !== 'string') {
      return res.status(400).json({
        success: false,
        error: '自定义文件名必须是字符串'
      });
    }

    if (!isValidFileName(customFileName)) {
      return res.status(400).json({
        success: false,
        error: '自定义文件名格式无效或包含不允许的字符'
      });
    }
  }

  next();
}

/**
 * 验证任务ID参数
 */
function validateTaskId(req, res, next) {
  const { id } = req.params;

  if (!isValidTaskId(id)) {
    return res.status(400).json({
      success: false,
      error: '无效的任务ID格式'
    });
  }

  next();
}

/**
 * 验证查询参数
 */
function validateQueryParams(req, res, next) {
  const { limit, status } = req.query;

  // 验证limit参数
  if (limit !== undefined) {
    const limitNum = parseInt(limit);
    if (isNaN(limitNum) || limitNum < 0 || limitNum > 1000) {
      return res.status(400).json({
        success: false,
        error: 'limit参数必须是0-1000之间的数字'
      });
    }
    req.query.limit = limitNum;
  }

  // 验证status参数
  if (status !== undefined) {
    const validStatuses = ['pending', 'downloading', 'completed', 'failed', 'cancelled'];
    if (!validStatuses.includes(status)) {
      return res.status(400).json({
        success: false,
        error: `status参数必须是以下值之一: ${validStatuses.join(', ')}`
      });
    }
  }

  next();
}

/**
 * 验证清理参数
 */
function validateCleanupParams(req, res, next) {
  const { maxAge } = req.body;

  if (maxAge !== undefined) {
    const maxAgeNum = parseInt(maxAge);
    if (isNaN(maxAgeNum) || maxAgeNum < 1 || maxAgeNum > 365) {
      return res.status(400).json({
        success: false,
        error: 'maxAge参数必须是1-365之间的数字（天数）'
      });
    }
    req.body.maxAge = maxAgeNum;
  }

  next();
}

/**
 * 通用错误处理中间件
 */
function errorHandler(err, req, res, next) {
  console.error('API错误:', err);

  // 如果响应已经发送，交给默认错误处理器
  if (res.headersSent) {
    return next(err);
  }

  // 业务逻辑错误
  if (err.message) {
    return res.status(400).json({
      success: false,
      error: err.message
    });
  }

  // 未知错误
  res.status(500).json({
    success: false,
    error: '服务器内部错误'
  });
}

/**
 * 404 处理中间件
 */
function notFoundHandler(req, res) {
  res.status(404).json({
    success: false,
    error: '接口不存在'
  });
}

/**
 * 日志中间件
 */
function requestLogger(req, res, next) {
  const start = Date.now();

  // 记录请求
  console.log(`📥 ${req.method} ${req.originalUrl} - ${req.ip}`);

  // 记录响应
  const originalSend = res.send;
  res.send = function (data) {
    const duration = Date.now() - start;
    console.log(`📤 ${req.method} ${req.originalUrl} - ${res.statusCode} - ${duration}ms`);
    originalSend.call(this, data);
  };

  next();
}

module.exports = {
  validateAddDownload,
  validateTaskId,
  validateQueryParams,
  validateCleanupParams,
  errorHandler,
  notFoundHandler,
  requestLogger,
  isValidUrl,
  isValidFileName,
  isValidTaskId
};
